<HTML><HEAD><TITLE>The PERN Project - Day 5</TITLE><META http-equiv="Content-Type" content="text/html; charset=iso-8859-1"><LINK rel=stylesheet href="tutorial.css" type="text/css"> </HEAD>
<BODY bgcolor="#FF9900" text="#000000" link="#0000FF">
<DIV align="center"> 
  <P align="center"><img src="../images/banner.jpg" width="586" height="100"></P>
  <P align="center">The Nintedo Reverse Engeneering Project</P>
</DIV>
<P align="center"><FONT size="4"><B><FONT size="6">Day 5</FONT></B></FONT></P>
<P>Today we will cover:</P>
<p class="Heading1">Direct Memory access (DMA)<br>
  <a href="tutorial_5.html#timers">Timers</a><br>
  <a href="tutorial_5.html#interupts">Interrupts</a></p>
<p class="Heading1">&nbsp;</p>
<p class="Heading1">But First get the source here: <a href="../Examples/Examples.htm">Mode7</a> 
  (this source is only good for GCC sorry)</p>
<p class="Heading1">Direct Memory Access (DMA)</p>
<p> <b>Direct memory access is a fast means of moving data from one area of memory 
  to another. There is special circuitry inside the GBA called, appropriately, 
  the DMA controller, with the soul purpose of copying data. This DMA controller 
  is very fast but unfortunately ties up the data bus, which means the GBA processor 
  must be halted during DMA transfers. This happens automatically though. There 
  are many uses for DMA as it is a quick controllable data copy that is faster 
  than the CPU could manage.</b></p>
<p><b>Using DMA is actually very simple. Basically you give the DMA controller 
  the address of the data you want to be copied. You then give it the address 
  you wish the data copied to. Finally you tell it the amount you want copied, 
  and the mode you want it copied in. The only interesting part of all that is 
  the transfer mode.</b></p>
<p><b>There are actually 4 different DMA channels on the GBA each with their own 
  priority. This does not mean that you can transfer 4 chunks of data simultaneously 
  unfortunately. Each channel has different uses and slightly different capabilities. 
  Here they are and there normal uses:<br>
  </b></p>
<p><b><span class="SourceKeywords">DMA 0</span>: This is the one with the highest 
  priority and will not be interrupted by other channels. It is used when timing 
  is critical such as copying new OAM data in on the HBLANK. Can only be used 
  on internal memory of the GBA. This means that you can not transfer data from 
  ROM with this channel.</b></p>
<p><b><span class="SourceKeywords">DMA 1</span> <span class="SourceKeywords">and 
  2</span>: These channels are used mainly for Direct sound and have a fairly 
  high priority. They can transfer data from any memory area and are the only 
  channels that can be used with the sound FIFO buffer (to be discussed when we 
  talk about sound)<br>
  </b></p>
<p><b><span class="SourceKeywords">DMA 3</span>: This is the general purpose DMA 
  channel and the one most often used for general data copies. It also can transfer 
  data to and from any area of memory.</b></p>
<p><b>Now it is time to discus the DMA transfer mode. The mode basically just 
  establishes when the DMA starts, and how much data is transferred per write 
  (16bits at a time or 32). It also controls whether or not it repeats the transfer 
  on its own and if so when. And last if you set it to repeat you can have it 
  alter the source or destination addresses automatically before the next transfer. 
  This is a very useful feature. An example of were this would be very beneficial 
  would be the infamous Mode 7 effect. This is the effect used in games like F-zero 
  and Mario cart. Basically to achieve that effect you just change the scaling 
  of the background every horizontal line so that it appears further away the 
  higher up the screen it goes. In one of my examples I will demonstrate this 
  using the DMA. Here is a break down of the mode control for DMA transfer:</b></p>
<p class="Heading1">REG_DMAxCNT</p>
<table cellspacing=0 cellpadding=0 border=1 align="center">
  <tbody> 
  <tr> 
    <td width=46><b> 31</b></td>
    <td width=46><b> 30</b></td>
    <td width=46><b> 29</b></td>
    <td width=46><b> 28</b></td>
    <td width=46><b> 27</b></td>
    <td width=46><b> 26</b></td>
    <td width=46><b> 25</b></td>
    <td width=46><b> 24</b></td>
    <td width=46><b> 23</b></td>
    <td width=46><b> 22</b></td>
    <td width=46><b> 21</b></td>
    <td width=46><b> 20</b></td>
    <td width=46><b> 19</b></td>
    <td width=46><b> 18</b></td>
    <td width=46><b> 17 </b></td>
    <td width=46><b> 16</b></td>
  </tr>
  <tr> 
    <td width=47 height="17"> 
      <div align="center"><b>Enable </b></div>
    </td>
    <td width=46 height="17"> 
      <div align="center"><b>IRQ</b></div>
    </td>
    <td colspan=2 height="17"> 
      <div align="center"><b>Timing</b></div>
    </td>
    <td width=46 height="17"> 
      <div align="center"><b>- </b></div>
    </td>
    <td width=46 height="17"> 
      <div align="center"><b>16/32 </b></div>
    </td>
    <td width=48 height="17"> 
      <div align="center"><b>Repeate </b></div>
    </td>
    <td colspan=2 height="17"> 
      <div align="center"><b></b><b>Source</b></div>
    </td>
    <td colspan=2 height="17"> 
      <div align="center"><b>Dest</b></div>
    </td>
    <td width=46 height="17"> 
      <div align="center"><b>-</b></div>
    </td>
    <td width=46 height="17"> 
      <div align="center"><b>-</b></div>
    </td>
    <td width=46 height="17"> 
      <div align="center"><b>-</b></div>
    </td>
    <td width=46 height="17"> 
      <div align="center"><b>-</b></div>
    </td>
    <td width=46 height="17"> 
      <div align="center"><b>-</b></div>
    </td>
  </tr>
  </tbody> 
</table>
<p><br>
</p>
<p><span class="TutorialComment">Bits 0-15: </span>This is the word count. The 
  value in these bit determine how many words are copied. </p>
<p><span class="TutorialComment">Bit 31:</span> This bit turns the DMA transfer 
  on. This should be the last bit you enable after setting up the addresses and 
  the rest of the mode. If this bit is 0 no DMA will take place.<br>
  <span class="TutorialComment">Bit 30:</span> Interrupt enable. This bit causes 
  the end of the DMA transfer to generate an interrupt.<br>
  <span class="TutorialComment">Bits 28-29:</span> Timing- these bits control 
  when the DMA actually begins. <br>
</p>
<blockquote>
  <p><span class="TutorialComment">00</span>-Start immediately. If so than as 
    soon as bit 15 is set to 1 the transfer will begin.<br>
    <span class="TutorialComment">01</span>-start at the Vblank. As soon as the 
    last horizontal line is drawn the DMA will commence.<br>
    <span class="TutorialComment">10</span>-start at the Hblank. Starts at the 
    next HBLANK.<br>
    <span class="TutorialComment">11</span>- invalid for all channels but DMA 
    channel 3. For 3 it means to start at the beginning of the rendering period 
    after the first line is drawn. It will cause a repeat every Hblank after the 
    first line is drawn allowing you to copy one lines worth of data into the 
    frame buffer. This is mainly for mode 3 graphics as they do not have a backbuffer. 
    It allows you to copy in the data for the next frame one line at a time (the 
    last one that was drawn). While GBA is drawing one line of the display you 
    are copying in the data to replace the line it just drew This ensures that 
    you are always updating the video buffer for the line that was already rendered 
    keeping you flicker free. . This mode is mainly to facilitate add on devices 
    such as cameras that will have streaming data. I have never tested this mode 
    so if any of you try it let me know how it goes.<br>
  </p>
</blockquote>
<p><span class="TutorialComment">Bit 26:</span> Word size- if zero it copies in 
  16-bit words. If 1 it copies in 32-bit words.<br>
  <span class="TutorialComment">Bit 25:</span> DMA repeat - this will cause the 
  DMA to repeat every Hblank or Vblank if you have that specified in your timing 
  bits.<br>
  <span class="TutorialComment">Bits 23-24:</span> These control your how your 
  source counter is affected by each transfer (by transfer I mean each word copied).<br>
</p>
<blockquote>
  <p><span class="TutorialComment">00</span>-increment-the source counter is incremented 
    after each transfer<br>
    <span class="TutorialComment">01</span>-decrement-the source counter is decremented 
    after each transfer<br>
    <span class="TutorialComment">10</span>-fixed-good for memory fills as the 
    same data will get copied each frame<br>
    <span class="TutorialComment">11</span>-invalid value<br>
  </p>
</blockquote>
<p><span class="TutorialComment">Bits 21-22:</span> These control your how your 
  destination counter is affected by each transfer.<br>
</p>
<blockquote>
  <p><span class="TutorialComment">00</span>-increment-the destination counter 
    is incremented after each transfer<br>
    <span class="TutorialComment">01</span>-decrement<br>
    <span class="TutorialComment">10</span>-fixed- direct sound FIFO access<br>
    <span class="TutorialComment">11</span>-this value is different for the Destination 
    control. When set it will increment. At the end of the transfer (this time 
    I mean the entire DMA) it will be reset to its initial value. This is what 
    we will be using for mode 7 effects. </p>
</blockquote>
<p><b>As you may have already guessed to do mode 7 effect we would precalculate 
  all the values that need to be stored in the Background scale and rotate registers 
  and set DMA to repeat every HBLANK. By setting the source to increment we can 
  copy in the whole table with out touching it until the end of the frame when 
  it will need to be reset. By setting the destination to &quot;increment and 
  reset&quot; we can copy to the same memory location every HBLANK without touching 
  that one either. Well actualy we will be doing mode7 with interupts as i gives 
  us much more control.</b></p>
<p><b><br>
  So first we will need a header function to define all these DMA modes and then 
  we need a function to do some DMA.</b></p>
<p><br>
  <span class="SourceKeywords">#include</span> &quot;gba.h&quot;<br>
  <span class="SourceComment">/******************************************\<br>
  * DMA.h by dovoto <br>
  \******************************************/</span></p>
<p><span class="SourceKeywords">#ifndef</span> DMA_H<br>
  <span class="SourceKeywords">#define</span> DMA_H</p>
<p class="SourceComment">//these defines let you control individual bit in the 
  control register</p>
<p><span class="SourceKeywords">#define</span> DMA_ENABLE 0x80000000<br>
  <span class="SourceKeywords">#define</span> DMA_INTERUPT_ENABLE 0x40000000<br>
  <span class="SourceKeywords">#define</span> DMA_TIMEING_IMMEDIATE 0x00000000<br>
  <span class="SourceKeywords">#define</span> DMA_TIMEING_VBLANK 0x10000000<br>
  <span class="SourceKeywords">#define</span> DMA_TIMEING_HBLANK 0x20000000<br>
  <span class="SourceKeywords">#define</span> DMA_TIMEING_SYNC_TO_DISPLAY 0x30000000<br>
  <span class="SourceKeywords">#define</span> DMA_16 0x00000000<br>
  <span class="SourceKeywords">#define </span>DMA_32 0x04000000<br>
  <span class="SourceKeywords">#define</span> DMA_REPEATE 0x02000000<br>
  <span class="SourceKeywords">#define</span> DMA_SOURCE_INCREMENT 0x00000000<br>
  <span class="SourceKeywords">#define</span> DMA_SOURCE_DECREMENT 0x00800000<br>
  <span class="SourceKeywords">#define</span> DMA_SOURCE_FIXED 0x01000000<br>
  <span class="SourceKeywords">#define</span> DMA_DEST_INCREMENT 0x00000000<br>
  <span class="SourceKeywords">#define</span> DMA_DEST_DECREMENT 0x00200000<br>
  <span class="SourceKeywords">#define</span> DMA_DEST_FIXED 0x00400000<br>
  <span class="SourceKeywords">#define</span> DMA_DEST_RELOAD 0x00600000</p>
<p class="SourceComment">//these defines group common options to save typing. 
  You may notice that I don't have to include the option to increment the source 
  and address register as that is the default.</p>
<p><span class="SourceKeywords">#define</span> DMA_32NOW DMA_ENABLE | DMA_TIMEING_IMMEDIATE 
  |DMA_32 <br>
  <span class="SourceKeywords">#define</span> DMA_16NOW DMA_ENABLE | DMA_TIMEING_IMMEDIATE 
  |DMA_16 </p>
<p><span class="SourceKeywords">#ifndef</span> DMA_C<br>
  <span class="SourceKeywords">extern void</span> DMACopy(<span class="SourceKeywords">u8</span> 
  channel, <span class="SourceKeywords">void*</span> source, <span class="SourceKeywords">void*</span> 
  dest, <span class="SourceKeywords">u32</span> WordCount, <span class="SourceKeywords">u32</span> 
  mode);<br>
  <span class="SourceKeywords">#endif</span><br>
  <span class="SourceKeywords">#endif</span> <span class="SourceComment">//end 
  interrupts.h</span></p>
<p><br>
  <span class="SourceComment">/************************************\<br>
  * DMA.c by dovoto *<br>
  \************************************/</span><br>
  <span class="SourceKeywords">#define</span> DMA_C<br>
  <span class="SourceKeywords">#include</span> &quot;DMA.h&quot;<br>
  <span class="SourceKeywords">#include</span> &quot;gba.h&quot;</p>
<p><br>
  <span class="SourceKeywords">void</span> DMA_Copy(<span class="SourceKeywords">u8</span> 
  channel, <span class="SourceKeywords">void*</span> source, <span class="SourceKeywords">void*</span> 
  dest, <span class="SourceKeywords">u32</span> WordCount, <span class="SourceKeywords">u32</span> 
  mode)<br>
  {<br>
  <span class="SourceKeywords">switch</span> (channel)<br>
  {<br>
  <span class="SourceKeywords">case</span> 0: <br>
  REG_DMA0SAD = (u32)source;<br>
  REG_DMA0DAD = (u32)dest; <br>
  REG_DMA0CNT = WordCount | mode;<br>
  <span class="SourceKeywords">break</span>;<br>
  <span class="SourceKeywords">case </span>1:<br>
  REG_DMA1SAD = (u32)source;<br>
  REG_DMA1DAD = (u32)dest;<br>
  REG_DMA1CNT = WordCount | mode;<br>
  <span class="SourceKeywords">break</span>;<br>
  <span class="SourceKeywords">case</span> 2:<br>
  REG_DMA2SAD = (u32)source;<br>
  REG_DMA2DAD = (u32)dest;<br>
  REG_DMA2CNT = WordCount | mode;<br>
  <span class="SourceKeywords">break</span>;</p>
<p> <span class="SourceKeywords">case</span> 3:<br>
  REG_DMA3SAD = (u32)source;<br>
  REG_DMA3DAD = (u32)dest;<br>
  REG_DMA3CNT = WordCount | mode;<br>
  <span class="SourceKeywords">break</span>;</p>
<p> }<br>
  }</p>
<p><b>The first and most obvious use of DMA is to get rid of our for loop that 
  copies in our sprite structure once per frame. That sounds easy enough. This 
  is what it looked like before:</b></p>
<p><span class="SourceKeywords">void </span>CopyOAM(<span class="SourceKeywords">void</span>)<br>
  {<br>
  <span class="SourceKeywords"> u16</span> loop;<br>
  <span class="SourceKeywords">u16</span>* temp;<br>
  temp = (<span class="SourceKeywords">u16</span>*)sprites;<br>
  <span class="SourceKeywords">for</span>(loop = 0; loop &lt; 128*4; loop++)<br>
  {<br>
  OAM[loop] = temp[loop];<br>
  }<br>
  }</p>
<p><b>And this is our new function using dma:</b></p>
<p><br>
  <span class="SourceKeywords">void</span> CopyOAM(<span class="SourceKeywords">void</span>)<br>
  {<br>
  DMACopy( 3,(<span class="SourceKeywords">void</span>*)sprites,(<span class="SourceKeywords">void</span>*)OAM,128*4, 
  DMA_16NOW);<br>
  }</p>
<p><b>Easy huh? Well this is actually a very poor way to do this. If you will 
  notice we would have the overhead of two function calls and all that variable 
  passing and that unnecessary switch statement. Seems kind of silly since the 
  whole point of DMA is speed. In reality you should write a separate function 
  for the different channels and modes of DMA transfer and there is no point in 
  wrapping that function up in the call to CopyOAM. We could just stick the DMACopy 
  right in our code. Or, and even better yet, put the following in place of our 
  call to CopyOAM:</b></p>
<p>REG_DMA3SAD = (<span class="SourceKeywords">u32</span>)sprites;<br>
  REG_DMA3DAD = (<span class="SourceKeywords">u32</span>)OAM;<br>
  REG_DMA3CNT = 128 * 4 |DMA_16NOW;</p>
<p><b>That gets rid of all the overhead and is the way it should be done for small 
  transfers like this. That is of course up to you though. I am just trying to 
  teach the workings of the hardware. Lets move onto something a little more interesting: 
  Interrupts.</b></p>
<p><br>
  <span class="Heading1"><a name="interupts"></a>Interrupts:</span></p>
<p> <b>What is an interrupt? Well it is much like it sounds actually. You program 
  is running along executing code in its proper fashion when something comes along 
  that really requires your CPUs attention. So your CPU, being the nice CPU it 
  is, stops what it is doing and takes care of the interruption. When it is done 
  it returns to the point in your code were it left off. The nice thing about 
  interrupts is that you get to choose both what the CPU does when interrupted 
  but what things can interrupt it.</b></p>
<p><b>The basic flow of the interrupt cycle is this. You enable interrupts to 
  occur by setting the lowest bit in a specific register called the interrupt 
  master enable register (REG_IME = 0x1). This tells the GBA that interrupts may 
  be processed. You then set the bits in the interrupt enable register (REG_IE) 
  to enable specific interrupts. Now you may think that should be all there is 
  to it but of course it is not. That will allow the GBA to process those specific 
  interrupts if they occur but you still need to tell the hardware to cause interrupts 
  when certain things happen. Unfortunately the commands for this are all spread 
  out. Fortunately we already know most of those commands. Take DMA for instance. 
  If you want DMA to cause an interrupt when it is finished you set REG_IME to 
  0x1, set the appropriate bit of REG_IE and then set the REG_DMA0CNT (or what 
  ever channel of DMA) to DMA_INTERUPT_ENABLE. This will do 3 things. 1st when 
  DMA 0 finishes its transfer it will send an interrupt signal to the CPU. Since 
  REG_IME is set that signal is allowed to pass. It is compared to the bits in 
  REG_IE and since that bit also is set it will interrupt the CPU and the CPU 
  will then go about trying to do what you want. All the other interrupts have 
  similar bits in there control registers to accomplish the same thing. In REG_DISPSTAT 
  there are the bits for enabling both the VBLANK and the HBLANK interrupts and 
  also the vertical count interrupt which can cause an interrupt at any vertical 
  line you chose. Since we have not seen this register before lets define its 
  bits:</b></p>
<p class="Heading1">REG_DISPSTAT</p>
<p class="Heading1"></p>
<p class="Heading1"></p>
<table cellspacing=0 cellpadding=0 border=1 align="center">
  <tbody> 
  <tr> 
    <td width=46><b> 15</b></td>
    <td width=46><b> 14</b></td>
    <td width=46><b> 13</b></td>
    <td width=46><b> 12</b></td>
    <td width=46><b> 11</b></td>
    <td width=46><b> 10</b></td>
    <td width=46><b> 9</b></td>
    <td width=46><b> 8</b></td>
    <td width=46><b> 7</b></td>
    <td width=46><b> 6</b></td>
    <td width=46><b> 5</b></td>
    <td width=46><b> 4</b></td>
    <td width=46><b> 3</b></td>
    <td width=46><b> 2</b></td>
    <td width=46><b> 1</b></td>
    <td width=46><b> 0</b></td>
  </tr>
  <tr> 
    <td colspan="10" height="16"> 
      <div align="center"><b>VCOUNT Setting</b></div>
      </td>
    <td height="16"> 
      <div align="center"><b>VCE</b></div>
    </td>
    <td width=46 height="16"> 
      <div align="center"><b>HBE</b></div>
    </td>
    <td width=46 height="16"> 
      <div align="center"><b>VBE</b></div>
    </td>
    <td width=46 height="16"> 
      <div align="center"><b>VC</b></div>
    </td>
    <td width=46 height="16"> 
      <div align="center"><b>HB</b></div>
    </td>
    <td width=46 height="16"> 
      <div align="center"><b>VB</b></div>
    </td>
  </tr>
  </tbody> 
</table>
<p></p>
<p><br>
  <span class="TutorialComment">Bit 0</span>: set if there is a vblank occurring&#133;Can 
  be used to check for entering the vblank period.<br>
  <span class="TutorialComment">Bit 1</span>: Set if an hblank period is occurring<br>
  <span class="TutorialComment">Bit 2</span>: Set if the vertical count register 
  (REG_VCOUNT) is equal t the vcount setting defined in bits 6-15. <br>
  <span class="TutorialComment">Bit 3</span>: enables the vblank interrupt.<br>
  <span class="TutorialComment">Bit 4</span>: enables the hblank interrupt.<br>
  <span class="TutorialComment">Bit 5</span>: enables vertical count interrupt. 
  <br>
  <span class="TutorialComment">Bits 6-15</span>: Determine when the vertical 
  count interrupt will occure. When REG_VCOUNT equals the number stored in these 
  bits an inerupt will occure if it has been enabled.</p>
<p> <b>I suppose I should now list all the things (14) that can cause an interrupt. 
  These happen to coincide with the bits in REG_IE. I am just going to show the 
  picture of REG_IE and then give the header file as each bit controls a separate 
  interrupt and I don't want to list them twice. The numbers in the header correspond 
  to the bits in REG_IE.</b></p>
<p class="Heading1">REG_IE</p>
<p class="Heading1"></p>
<table cellspacing=0 cellpadding=0 border=1 align="center">
  <tbody> 
  <tr> 
    <td width=46 height="19"><b> 15</b></td>
    <td width=46 height="19"><b> 14</b></td>
    <td width=46 height="19"><b> 13</b></td>
    <td width=46 height="19"><b> 12</b></td>
    <td width=46 height="19"><b> 11</b></td>
    <td width=46 height="19"><b> 10</b></td>
    <td width=46 height="19"><b> 9</b></td>
    <td width=46 height="19"><b> 8</b></td>
    <td width=46 height="19"><b> 7</b></td>
    <td width=46 height="19"><b> 6</b></td>
    <td width=46 height="19"><b> 5</b></td>
    <td width=46 height="19"><b> 4</b></td>
    <td width=46 height="19"><b> 3</b></td>
    <td width=46 height="19"><b> 2</b></td>
    <td width=46 height="19"><b> 1</b></td>
    <td width=46 height="19"><b> 0</b></td>
  </tr>
  <tr> 
    <td height="16"> 
      <div align="center"><b>-</b></div>
    </td>
    <td height="16"> 
      <div align="center"><b>-</b></div>
    </td>
    <td height="16"> 
      <div align="center"><b>Cart</b></div>
    </td>
    <td height="16"> 
      <div align="center"><b>Key</b></div>
    </td>
    <td height="16"> 
      <div align="center"><b>DMA3</b></div>
    </td>
    <td height="16"> 
      <div align="center"><b>DMA2</b></div>
    </td>
    <td height="16"> 
      <div align="center"><b>DMA1</b></div>
    </td>
    <td height="16"> 
      <div align="center"><b>DMA0</b></div>
    </td>
    <td height="16"> 
      <div align="center"><b>COM</b></div>
    </td>
    <td height="16"> 
      <div align="center"><b>T3</b></div>
    </td>
    <td height="16"> 
      <div align="center"><b>T2</b></div>
    </td>
    <td width=46 height="16"> 
      <div align="center"><b>T1</b></div>
    </td>
    <td width=46 height="16"> 
      <div align="center"><b>T0</b></div>
    </td>
    <td width=46 height="16"> 
      <div align="center"><b>VC</b></div>
    </td>
    <td width=46 height="16"> 
      <div align="center"><b>HB</b></div>
    </td>
    <td width=46 height="16"> 
      <div align="center"><b>VB</b></div>
    </td>
  </tr>
  </tbody> 
</table>
<p>&nbsp;</p>
<p></p>
<p><span class="SourceKeywords">#ifndef</span> INTERUPT_H<br>
  <span class="SourceKeywords">#define</span> INTERUPT_H</p>
<p><span class="SourceKeywords">#include</span> &quot;gba.h&quot;</p>
<p><span class="SourceKeywords">#ifndef</span> INTERUPT_C</p>
<p class="SourceComment">//a couple of functions to make turing interrupts on 
  and off easier</p>
<p><span class="SourceKeywords">void</span> EnableInterupts(<span class="SourceKeywords">u16</span> 
  interupts);<br>
  <span class="SourceKeywords">void</span> DissableInterupts(<span class="SourceKeywords">u16</span> 
  interupts);</p>
<p class="SourceKeywords">#endif</p>
<p><span class="SourceKeywords">#define</span> INT_VBLANK 0x0001<br>
  <span class="SourceKeywords">#define</span> INT_HBLANK 0x0002 <br>
  <span class="SourceKeywords">#define</span> INT_VCOUNT 0x0004 <span class="SourceComment">//you 
  can set the display to generate an interrupt when it reaches a particular line 
  on the screen</span><br>
  <span class="SourceKeywords">#define</span> INT_TIMMER0 0x0008<br>
  <span class="SourceKeywords">#define</span> INT_TIMMER1 0x0010<br>
  <span class="SourceKeywords">#define</span> INT_TIMMER2 0x0020 <br>
  <span class="SourceKeywords">#define</span> INT_TIMMER3 0x0040<br>
  <span class="SourceKeywords">#define</span> INT_COMUNICATION 0x0080 <span class="SourceComment">//serial 
  communication interupt</span><br>
  <span class="SourceKeywords">#define</span> INT_DMA0 0x0100<br>
  <span class="SourceKeywords">#define </span>INT_DMA1 0x0200<br>
  <span class="SourceKeywords">#define</span> INT_DMA2 0x0400<br>
  <span class="SourceKeywords">#define</span> INT_DMA3 0x0800<br>
  <span class="SourceKeywords">#define</span> INT_KEYBOARD 0x1000<br>
  <span class="SourceKeywords">#define </span>INT_CART 0x2000 <span class="SourceComment">//the 
  cart can actually generate an interupt</span><br>
  <span class="SourceKeywords">#define</span> INT_ALL 0x4000 <span class="SourceComment">//this 
  is just a flag we can set to allow the my function to enable or disable all 
  interrupts. Doesn't actually correspond to a bit in REG_IE </span></p>
<p><span class="SourceKeywords">#endif</span></p>
<p><br>
  <b>Before we actually talk about writing some interrupt code we need a bit more 
  detail as to what the GBA will do when it encounters an interrupt. When an interrupt 
  occurs, assuming your registers are set correctly, the CPU stops what it is 
  doing and passes control to the bios. Inside the bios is a short function that 
  saves the values in the registers along with the address that it just came from 
  to allow the CPU to restore its initial condition when the interrupt is over. 
  It then passes control to the address stored in the memory address 0x3007FFC. 
  This is where we need to put our interrupt handler. What do I mean by that? 
  That just means that the we need to point that register to our interrupt handler 
  by making it equal to our interrupt handlers address. All interrupts that occur 
  will pass the program flow to this address. It is up to us to figure out what 
  interrupt actually caused the event. The way we do that is check another register 
  REG_IF. This register has the exact same bit layout as REG_IE so we can use 
  the same interrupt header to check this register. After processing the interrupt 
  we must clear the bit in REG_IF that corresponds to the interrupt we just serviced. 
  This register is very odd in that it requires us to right a 1 bit to the register 
  in order to clear it instead of a zero. So to check to see if the VBLANK interrupt 
  has occurred we would say :</b></p>
<p><br>
  <span class="SourceKeywords">If</span>(REG_IF == INT_VBLANK) <br>
  {<br>
  <span class="SourceComment">//do vblank stuff</span><br>
  }</p>
<p><br>
  <b>to reset that register and let the GBA know that we have processed it we 
  add this line to the end of the VBLANK handler:</b></p>
<p>REG_IF | = INT_VBLANK;</p>
<p><b>And that's it. Now fortunately for us, crt0.s or boot.asm takes care of 
  most of this for us(crt0.s is the startup code for GCC while boot.asm is the 
  startup code for arm sdt). It has a simple interrupt handler inside that is 
  loaded into 0x3007FFC and checks the IF flag for us. It then branches to a table 
  of functions that we can define. This may not make sense as you probably have 
  never seen a table of functions before but I will try to explain. Basically 
  it is just a list of function names that can be called by the interrupt handler 
  inside the startup code.<br>
  The start up code is going to look for a table called IntrTable[14] ={&#133;}. 
  If we define that table in our c file somewhere and fill it with interrupt handling 
  functions the startup code will handle the rest. Here is my interrupt c code, 
  it is large so I will put it in a popup window to avoid cluttering this tutor.</b></p>
<p><br>
  <a href="interupt.c">INTERUPT.C</a></p>
<p><br>
  <b>Crt0.s does not automatically include support for interrupts. There is a 
  line you must comment out in order to use them. It is easy to find though and 
  the implementation of GCC that is distributed from my site has them already 
  included. Once this is done you must always define an IntrTable somewhere or 
  you will get link errors. That is really all there is to interrupts. As always 
  if something is unclear or I missed something that I just assumed you would 
  know then please tell me so I can fix it. I don't mind stupid questions.</b></p>
<p><br>
  <span class="Heading1"><a name="timers"></a>Timers.</span></p>
<p><b>Okay timers are fairly simple devices. They count up based on system clock. 
  The GBA has four 16 bit timers that are very simple to control. They count from 
  0 to 2^16 (that's 65,535). You can choose four different frequencies for them 
  to count at:</b></p>
<blockquote>
  <p><br>
    At system clock frequency: 16.78 MHZ or about 59.595 nano seconds<br>
    Every 64 clock pulses or about 3.814 micro seconds<br>
    Every 256 clock pulses or about every 15.256 micro seconds<br>
    Every 1024 clock pulses or about every 61.025 micro seconds</p>
</blockquote>
<p><b>So if you started a clock at zero at 1024 clock pulse frequency it will 
  read about 16386 after one second. You can also cause one timer to overflow 
  into the next one. Lets define the bits of the timer control registers and make 
  a simple function that waits x number of seconds. The timer can be read at their 
  respective data registers (REG_TMxD where x is the timer number);</b></p>
<p class="Heading1">REG_TMxCNT</p>
<p class="Heading1"></p>
<table cellspacing=0 cellpadding=0 border=1 align="center">
  <tbody> 
  <tr> 
    <td width=46><b> 15</b></td>
    <td width=46><b> 14</b></td>
    <td width=46><b> 13</b></td>
    <td width=46><b> 12</b></td>
    <td width=46><b> 11</b></td>
    <td width=46><b> 10</b></td>
    <td width=46><b> 9</b></td>
    <td width=46><b> 8</b></td>
    <td width=46><b> 7</b></td>
    <td width=46><b> 6</b></td>
    <td width=46><b> 5</b></td>
    <td width=46><b> 4</b></td>
    <td width=46><b> 3</b></td>
    <td width=46><b> 2</b></td>
    <td width=46><b> 1</b></td>
    <td width=46><b> 0</b></td>
  </tr>
  <tr> 
    <td height="22"> 
      <div align="center"><b>-</b></div>
    </td>
    <td height="22"> 
      <div align="center"><b>-</b></div>
    </td>
    <td height="22"> 
      <div align="center"><b>-</b></div>
    </td>
    <td height="22"> 
      <div align="center"><b>-</b></div>
    </td>
    <td height="22"> 
      <div align="center"><b>-</b></div>
    </td>
    <td height="22"> 
      <div align="center"><b>-</b></div>
    </td>
    <td height="22"> 
      <div align="center"><b>-</b></div>
    </td>
    <td height="22"> 
      <div align="center"><b>-</b></div>
    </td>
    <td height="22"> 
      <div align="center"><b>Enable</b></div>
    </td>
    <td height="22"> 
      <div align="center"><b>IRQ</b></div>
    </td>
    <td height="22"> 
      <div align="center"><b>-</b></div>
    </td>
    <td width=46 height="22"> 
      <div align="center"><b>-</b></div>
    </td>
    <td width=46 height="22"> 
      <div align="center"><b>-</b></div>
    </td>
    <td width=46 height="22"> 
      <div align="center"><b>O F</b></div>
    </td>
    <td colspan="2" height="22"> 
      <div align="center"><b>Freq</b></div>
    </td>
  </tr>
  </tbody> 
</table>
<p><span class="TutorialComment">Bits 0-1</span>: Select frequancy</p>
<p><span class="TutorialComment">Bit 2</span>: When set, if the timer below it 
  overflows this timer will be automaticaly incremented.</p>
<p><span class="TutorialComment">Bit 6</span>: When set the timer will generate 
  an interupt upon over flow.</p>
<p><span class="TutorialComment">Bit 7</span>: When set the timer will be operating.</p>
<p><span class="SourceComment">/************************************\<br>
  * Timers.h by dovoto *<br>
  \************************************/</span><br>
  <span class="SourceKeywords">#ifndef</span> TIMERS_H<br>
  <span class="SourceKeywords">#define </span>TIMERS_H</p>
<p><br>
  <span class="SourceKeywords">#define</span> TIME_FREQUENCY_SYSTEM 0x0<br>
  <span class="SourceKeywords">#define</span> TIME_FREQUENCY_64 0x1<br>
  <span class="SourceKeywords">#define</span> TIME_FREQUENCY_256 0x2<br>
  <span class="SourceKeywords">#define</span> TIME_FREQUENCY_1024 0x3<br>
  <span class="SourceKeywords">#define</span> TIME_OVERFLOW 0x4<br>
  <span class="SourceKeywords">#define</span> TIME_ENABLE 0x80<br>
  <span class="SourceKeywords">#define</span> TIME_IRQ_ENABLE 0x40</p>
<p class="SourceKeywords">#endif</p>
<p><b>All right and here is our simple function to wait a few seconds</b></p>
<p><span class="SourceKeywords">void</span> Wait(<span class="SourceKeywords">int</span> 
  seconds)<br>
  {<br>
  <span class="SourceComment">//Start the timer</span><br>
  REG_TM3CNT = TIME_FREQUENCY_1024 | TIME_ENABLE;<br>
  <span class="SourceComment">//zero the timer</span><br>
  REG_TM3D = 0;<br>
  <span class="SourceKeywords">while</span>(seconds--)<br>
  {<br>
  <span class="SourceKeywords">while</span>(REG_TM3D &lt;= 16386){}<span class="SourceComment"> 
  //wait</span><br>
  REG_TM3D = 0; <span class="SourceComment">//reset the timmer</span><br>
  }<br>
  }</p>
<p><b>Now a few things more about timers and we will call it a day. If you set 
  one timer to overflow (say timer 3) then every time the timer below it (in this 
  case timer 2) overflows then that timer (3) will be incremented. This allows 
  longer measures of time. Personally I like to use interrupts for this. I have 
  the timer generate an interrupt which increments a variable. This saves me the 
  use of one of my timers and still allows for very long amounts of time to be 
  measured in my game. One last thing. When a timer overflows it will go back 
  to zero by default but if you ever write a value to the data register it will, 
  from then on, start its count at that value instead of zero. So if you write 
  32768 to a data register it will over flow twice as fast from then on (until 
  you write a new value to it). This is called latching the timer and allows for 
  fine control over the timer. One obvious use of this feature would be to write 
  the value 41950 (65536 - 16386) to a timer that is counting every 1024 clock 
  pulses so that it overflows every second. Then you have it generate an interrupt 
  that looks something like this:</b></p>
<p><span class="SourceKeywords">void</span> Timer3(<span class="SourceKeywords">void</span>) 
  <span class="SourceComment">//my timer interupt</span><br>
  {<br>
  seconds++; <span class="SourceComment">// a second has elapsed so lets increment</span><br>
  <span class="SourceKeywords">if</span> (seconds &gt;= 60)<br>
  {<br>
  seconds = 0;<br>
  minutes++;<br>
  }<br>
  <span class="SourceKeywords">if</span>(minutes &gt;=60)<br>
  {<br>
  minutes = 0;<br>
  hours++;<br>
  }<br>
  <span class="SourceKeywords">if</span>(hours &gt;=24)<br>
  {<br>
  hours = 0;<br>
  days++;<br>
  }<br>
  }</p>
<p><b>Kind of cool huh? </b></p>
<p><b>Actualy if you had been paying attention you may have noticed that I went 
  about waiting for one second in a very odd matter. If I had just set the frequency 
  to 256 instead of 1024 it would have overflowed every second automaticaly. I 
  would like to say I did this just so I could show you all the features of the 
  timers but in actuality I just did not realize it. Thanks to StaringMonkey for 
  pointing this out to me. Well that's it for today. If anyone wants to write 
  some simple examples I would be glad to post them on my site. A mode 7 type 
  effect would be most appreciated. Just think: Tomorrow you get to put sound 
  in your game.</b><br>
  <br>
</p>
<P align="center"><a href="http://www.success-hk.com/affiliatewiz/aw.asp?B=2&A=9&Task=Click" target="_blank" > 
  <img src="../images/F2A256.jpg" width="350" height="225" alt="Gameboy Advance Flash Linker" border="0"></a></P>
<P align="center"><a href="tutorial_4.html">Back</a> <BR>
   </P></BODY></HTML> 
